Skip to content

Conversation

konono
Copy link

@konono konono commented Sep 22, 2025

Description

Linked issue: #845

What is being changed?

  • Fix evaluation logic in _process_user_value:
    • Apply ANY semantics (short-circuit on first match) for attributes with multiple values.
    • Treat empty/falsy attributes as no match, log debug message, and join False.
  • Add optional-dependencies.dev in pyproject.toml.
  • Update test_claims.py expectations and add regression cases.

Why is this change needed?

The previous implementation folded each value into has_access_with_join iteratively, effectively resulting in AND semantics, which caused false negatives when only one match should allow access.
Also, empty attributes were not properly handled.

How does this change address the issue?

  • Implements proper ANY semantics at the attribute level.
  • Handles empty attributes explicitly as no match.
  • Expands test coverage to ensure correctness.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Test update
  • Refactoring (no functional changes)
  • Development environment change
  • Configuration change

Testing Instructions

Prerequisites

  • Run rye sync --features "rbac,feature_flags,testing,dev"
  • Set environment variable: DJANGO_SETTINGS_MODULE=test_app.sqlite3settings

Steps to Test

  1. Set up the test environment.

  2. Run the following tests:

    rye run pytest test_app/tests/authentication/utils/test_claims.py --color=yes -q
  3. Verify that all tests pass.

     ❯ rye run pytest test_app/tests/authentication/utils/test_claims.py -q --color=yes
     ============================================================================================ test session starts =============================================================================================
     platform darwin -- Python 3.11.9, pytest-8.4.2, pluggy-1.6.0 -- /Users/yyamashi/gitrepo/django-ansible-base/.venv/bin/python3
     cachedir: .pytest_cache
     django: version: 4.2.21, settings: test_app.sqlite3settings (from env)
     rootdir: /Users/yyamashi/gitrepo/django-ansible-base
     configfile: pyproject.toml
     plugins: asyncio-1.2.0, xdist-3.8.0, django-4.11.1, typeguard-4.4.4, cov-7.0.0
     asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
     collected 240 items
     ===SNIP===
     test_app/tests/authentication/utils/test_claims.py::TestClaimsHelperFunctions::test_normalize_user_value[string_value-expected0] PASSED                                                                [ 98%]
     test_app/tests/authentication/utils/test_claims.py::TestClaimsHelperFunctions::test_normalize_user_value[user_value1-expected1] PASSED                                                                 [ 98%]
     test_app/tests/authentication/utils/test_claims.py::TestClaimsHelperFunctions::test_normalize_user_value[123-expected2] PASSED                                                                         [ 99%]
     test_app/tests/authentication/utils/test_claims.py::TestClaimsHelperFunctions::test_normalize_user_value[None-expected3] PASSED                                                                        [ 99%]
     test_app/tests/authentication/utils/test_claims.py::TestClaimsHelperFunctions::test_normalize_user_value[user_value4-expected4] PASSED                                                                 [100%]
     
     ============================================================================================ 240 passed in 14.22s ============================================================================================

Expected Results

  • Attributes with multiple values allow access if any value matches.
  • Empty attributes are treated as no match (SKIP).
  • Regression cases (cn / employeeType with AND/OR conditions) behave as expected.

Additional Context

  • This change fixes a functional bug without introducing breaking changes.
  • Strengthened test coverage to prevent regressions.

Required Actions

…andling

When a user attribute has multiple values, _process_user_value now evaluates
them with ANY semantics (short-circuit on first match) and joins the result
once via has_access_with_join. Previously we folded each element into
has_access on every iteration, which effectively behaved like an AND across
values and produced false negatives.

Also treat empty/falsey user_value as no match and log a debug line,
then join False for the attribute. This aligns attribute-level behavior with
expected trigger semantics.

Tests: update the explicit 'and' + list case to expect ALLOW on single
match; add regression cases for cross-attribute AND/OR (cn contains 'ldap',
employeeType contains 'manager').

Signed-off-by: yyuki <[email protected]>
Copy link

DVCS PR Check Results:

PR appears valid (JIRA key(s) found)

optional-dependencies.oauth2_provider = { file = [ "requirements/requirements_oauth2_provider.in" ] }
optional-dependencies.resource_registry = { file = [ "requirements/requirements_resource_registry.in" ] }
optional-dependencies.feature_flags = { file = [ "requirements/requirements_feature_flags.in" ] }
optional-dependencies.dev = { file = [ "requirements/requirements_dev.txt" ] }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting. I don't think this is a bad idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants